import os
import json
import sys

# 生成单个文件的编译命令
# - 使用 C++20（与工程 CMake 配置一致）
# - 聚合常用的头文件搜索路径，并支持通过环境变量追加第三方头文件目录
# - 给文件路径加引号，兼容带空格路径
# - 返回完整的命令字符串（"command" 字段）
def generate_compile_command(file_path, project_root):
    relative_includes = [
        'src',
        'src/common/include',
        'src/fiber/include',
        'src/raftClerk/include',
        'src/raftCore/include',
        'src/raftRpcPro/include',
        'src/rpc/include',
        'src/skipList/include',
        'example',  # 解析 example 下头文件（如 rpcExample/friend.pb.h）
    ]

    # 允许通过环境变量追加三方/本地的 include 目录
    # 可用变量：EXTRA_INCLUDE_DIRS、PROTOBUF_INCLUDE、MUDUO_INCLUDE（用 os.pathsep 分隔多个路径）
    extra_includes = []
    for env in ('EXTRA_INCLUDE_DIRS', 'PROTOBUF_INCLUDE', 'MUDUO_INCLUDE'):
        val = os.environ.get(env)
        if val:
            extra_includes += [p for p in val.split(os.pathsep) if p]

    include_flags = ' '.join(
        [f'-I{os.path.join(project_root, inc)}' for inc in relative_includes]
        + [f'-I{p}' for p in extra_includes]
    )

    # 允许通过环境变量追加额外编译标志（如宏定义等）
    extra_flags = os.environ.get('EXTRA_FLAGS', '')

    # 使用 clang++ C++20，保持与工程一致
    return f'clang++ -std=c++20 -c "{file_path}" {include_flags} {extra_flags}'.strip()


def main():
    project_root = os.path.abspath(os.path.dirname(__file__))
    compile_commands = []

    # 跳过常见的生成/缓存目录，避免噪声
    skip_dirs = {'.git', '.vs', 'out', 'build', 'bin', 'lib', '.cache', '__pycache__'}

    for root, dirs, files in os.walk(project_root):
        # 过滤要跳过的目录（就地修改 dirs 才会生效）
        dirs[:] = [d for d in dirs if d not in skip_dirs]

        for file in files:
            if file.endswith('.cpp') or file.endswith('.cc'):
                full_path = os.path.join(root, file)
                command = generate_compile_command(full_path, project_root)
                # 关键：把 directory 设为当前源文件所在目录，确保相对包含（如同目录 .h）能被正确解析
                compile_commands.append({
                    'directory': root,
                    'command': command,
                    'file': full_path
                })

    output_path = os.path.join(project_root, 'compile_commands.json')
    with open(output_path, 'w', encoding='utf-8') as f:
        json.dump(compile_commands, f, indent=4, ensure_ascii=False)
    print(f'Generated {output_path} with {len(compile_commands)} entries')


if __name__ == '__main__':
    main()